The goals / steps of this project are the following:
import matplotlib.pyplot as plt
%matplotlib inline
import glob
from camera_calibration import CameraCalibrator, plot_single_camera_image_using_calibrator
from lane_detection import LaneDetectionPipeline
from image_utils import *
from perspective_transform import BirdsEyeViewTransform
from lane_finding_histogram import *
Most of the chessboard camera images have 9x6 visible corners, except a couple which only have 9x5 visible corners.
I start by preparing "object points", which will be the (x, y, z) coordinates of the chessboard corners in the world. Here I am assuming the chessboard is fixed on the (x, y) plane at z=0, such that the object points are the same for each calibration image. Thus, objp is just a replicated array of coordinates, and objpoints will be appended with a copy of it every time I successfully detect all chessboard corners in a test image.
imgpoints will be appended with the (x, y) pixel position of each of the corners in the image plane with each successful chessboard detection.
I then used the output objpoints and imgpoints to compute the camera calibration and distortion coefficients using the cv2.calibrateCamera() function. Calibration matrix and distortion are saved to models/camera_calibration_model.
In the code below, I am loading the calibration model to memory, and displaying chess board images post distortion and perspective transformation.
calibrator = CameraCalibrator()
calibrator.restore('models/camera_calibration_model')
sample_camera_images_and_corners = [
(cv2.imread('camera_cal/calibration1.jpg'), 9, 5),
(cv2.imread('camera_cal/calibration2.jpg'), 9, 6),
(cv2.imread('camera_cal/calibration3.jpg'), 9, 6),
(cv2.imread('camera_cal/calibration6.jpg'), 9, 6),
(cv2.imread('camera_cal/calibration8.jpg'), 9, 6),
(cv2.imread('camera_cal/calibration10.jpg'), 9, 6)]
for img, nx, ny in sample_camera_images_and_corners:
plot_single_camera_image_using_calibrator(img, nx, ny, calibrator)
plt.show()
## helper to display image grid
def grid_plot(image_cols):
ncols = len(image_cols)
nrows = len(image_cols[0][1])
fig, axes = plt.subplots(nrows, ncols, figsize = (8*ncols, 4*nrows))
fig.tight_layout()
fig.subplots_adjust(wspace = 0.1, hspace=0.1, )
for r, ax in enumerate(axes):
for c, (colname, imgs) in enumerate(image_cols):
img = imgs[r]
cmap = plt.cm.gray if img.ndim < 3 else None
ax[c].imshow(img, cmap=cmap)
ax[c].set_axis_off()
ax[c].set_title(colname)
The pipeline I am using to process images and identify lanes contains these following steps:
Here are results of applying distortion correction on test road images:
test_img_files = glob.glob("test_images/*.jpg")
test_images = [read_image_as_rgb(f) for f in test_img_files]
undist_images = [calibrator.undistort(img) for img in test_images]
grid_plot( [("original", test_images),
("undistorted", undist_images)])